package com.stary.pay.unionpay.api.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertStore;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathBuilderResult;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.security.spec.RSAPublicKeySpec;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.stary.pay.unionpay.api.UnionpayConstants;

/**
 * <p>证书处理类，主要用于对证书的使用</p>
 * @author stary {@link stary1993@qq.com}
 * @since 2019-6-24
 */
public class UnionpayCertHolder {

	/** 证书容器，存储对商户请求报文签名私钥证书. */
	private static KeyStore keyStore = null;
	/** 敏感信息加密公钥证书 */
	private static X509Certificate encryptCert = null;
	/** 磁道加密公钥 */
	private static PublicKey encryptTrackKey = null;
	/** 验证银联返回报文签名证书. */
	private static X509Certificate validateCert = null;
	/** 验签中级证书 */
	private static X509Certificate middleCert = null;
	/** 验签根证书 */
	private static X509Certificate rootCert = null;
	/** 验证银联返回报文签名的公钥证书存储Map. */
	private static Map<String, X509Certificate> certMap = new HashMap<String, X509Certificate>();
	/** 商户私钥存储Map */
	private final static Map<String, KeyStore> keyStoreMap = new ConcurrentHashMap<String, KeyStore>();

	/**
	 * 添加签名，验签，加密算法提供者
	 */
	public static void addProvider(){
		if (Security.getProvider("BC") == null) {
			Security.addProvider(new BouncyCastleProvider());
			UnionpayUtils.getLogger().info("add BC provider succeed");
		} else {
			Security.removeProvider("BC"); //解决eclipse调试时tomcat自动重新加载时，BC存在不明原因异常的问题。
			Security.addProvider(new BouncyCastleProvider());
			UnionpayUtils.getLogger().info("re-add BC provider succeed");
		}
		printSysInfo();
	}

	/**
	 * 配置的私钥路径和密码 加载签名证书
	 * @param signMethod
	 * @param signCertFile
	 * @param signCertPwd
	 * @param signCertType
	 */
	public static void initSignCert(String signMethod, String signCertFile, 
			String signCertPwd, String signCertType) {
		if (!UnionpayConstants.SIGNMETHOD_RSA.equals(signMethod)) {
			UnionpayUtils.getLogger().warn("signMenthod is not RSA,no sign cert is loaded");
			return;
		}
		if (StringUtils.isEmpty(signCertFile) || StringUtils.isEmpty(signCertPwd) 
				|| StringUtils.isEmpty(signCertType)) {
			UnionpayUtils.getLogger().error("signCertFile or signCertPwd or signCertType is empty,stop loading this sign cert");
			return;
		}
		if (keyStore != null) {
			keyStore = null;
		}
		try {
			keyStore = getKeyInfo(signCertFile, signCertPwd, signCertType);
			UnionpayUtils.getLogger().info("init sign cert was succeed.CertId=[" + getSignCertId() + "]");
		} catch (IOException e) {
			UnionpayUtils.getLogger().error("sign cert init error", e);
		}
	}

	/**
	 * 加载敏感信息加密证书
	 * @param middleCertFile
	 */
	public static void initMiddleCert(String middleCertFile) {
		UnionpayUtils.getLogger().debug(middleCertFile + " middleCertFile is loading...");
		if (!StringUtils.isEmpty(middleCertFile)) {
			middleCert = initCert(middleCertFile);
			UnionpayUtils.getLogger().info("init middle cert succeed");
		} else {
			UnionpayUtils.getLogger().warn("middleCertFile is empty");
		}
	}

	/**
	 * 加载敏感信息加密证书
	 * @param rootCertFile
	 */
	public static void initRootCert(String rootCertFile) {
		UnionpayUtils.getLogger().debug(rootCertFile + " rootCertFile is loading...");
		if (!StringUtils.isEmpty(rootCertFile)) {
			rootCert = initCert(rootCertFile);
			UnionpayUtils.getLogger().info("init root cert succeed");
		} else {
			UnionpayUtils.getLogger().warn("rootCertFile is empty");
		}
	}

	/**
	 * 加载银联公钥上级证书（中级证书）
	 * @param encryptCertFile
	 */
	public static void initEncryptCert(String encryptCertFile) {
		UnionpayUtils.getLogger().debug(encryptCertFile + " encryptCertFile is loading...");
		if (!StringUtils.isEmpty(encryptCertFile)) {
			encryptCert = initCert(encryptCertFile);
			UnionpayUtils.getLogger().info("init encrypt cert succeed");
		} else {
			UnionpayUtils.getLogger().warn("encryptCertFile is empty");
		}
	}

	/**
	 * 加载磁道公钥
	 * @param encryptTrackKeyModulus
	 * @param encryptTrackKeyExponent
	 */
	public static void initTrackKey(String encryptTrackKeyModulus, String encryptTrackKeyExponent) {
		if (!StringUtils.isEmpty(encryptTrackKeyModulus) 
				&& !StringUtils.isEmpty(encryptTrackKeyExponent)) {
			encryptTrackKey = getPublicKey(encryptTrackKeyModulus, encryptTrackKeyExponent);
			UnionpayUtils.getLogger().info("init track key succeed");
		} else {
			UnionpayUtils.getLogger().warn("encryptTrackKeyModulus or encryptTrackKeyExponent is empty");
		}
	}

	/**
	 * 加载验证签名证书 version 5.0.0
	 * @param signMethod
	 * @param validateCertDir
	 */
	public static void initValidateCertFromDir(String signMethod, String validateCertDir) {
		if (!UnionpayConstants.SIGNMETHOD_RSA.equals(signMethod)) {
			UnionpayUtils.getLogger().warn("signMenthod is not RSA,no sign cert is loaded");
			return;
		}
		certMap.clear();
		UnionpayUtils.getLogger().debug(validateCertDir + " validateCertDir is loading...");
		if (StringUtils.isEmpty(validateCertDir)) {
			UnionpayUtils.getLogger().warn("validateCertDir is empty");
			return;
		}
		CertificateFactory cf = null;
		FileInputStream in = null;
		try {
			cf = CertificateFactory.getInstance("X.509", "BC");
		}catch (NoSuchProviderException e) {
			UnionpayUtils.getLogger().error("init verify cert error:no BC Provider", e);
			return ;
		} catch (CertificateException e) {
			UnionpayUtils.getLogger().error("init verify cert error", e);
			return ;
		}
		File fileDir = new File(validateCertDir);
		File[] files = fileDir.listFiles(new CerFilter());
		for (int i = 0; i < files.length; i++) {
			File file = files[i];
			try {
				in = new FileInputStream(file.getAbsolutePath());
				validateCert = (X509Certificate) cf.generateCertificate(in);
				if(validateCert == null) {
					UnionpayUtils.getLogger().error("init verify cert error, " + file.getAbsolutePath() + " has error cert content");
					continue;
				}
				certMap.put(validateCert.getSerialNumber().toString(), validateCert);
				// 打印证书加载信息,供测试阶段调试
				UnionpayUtils.getLogger().debug("[" + file.getAbsolutePath() + 
						"][certId=" + validateCert.getSerialNumber().toString() + "]");
			} catch (CertificateException e) {
				UnionpayUtils.getLogger().error("init verify cert error", e);
			} catch (FileNotFoundException e) {
				UnionpayUtils.getLogger().error("init verify cert error:file not found", e);
			} finally {
				if (null != in) {
					try {
						in.close();
					} catch (IOException e) {
						UnionpayUtils.getLogger().error(e.toString());
					}
				}
			}
		}
		UnionpayUtils.getLogger().info("init verify cert finish");
	}

	/**
	 * 用给定的路径和密码 加载签名证书，并保存到certKeyStoreMap
	 * @param certFilePath
	 * @param certPwd
	 */
	private static void loadSignCert(String certFilePath, String certPwd) {
		KeyStore keyStore = null;
		try {
			keyStore = getKeyInfo(certFilePath, certPwd, UnionpayConstants.SIGN_CERT_TYPE_PKCS12);
			keyStoreMap.put(certFilePath, keyStore);
			UnionpayUtils.getLogger().debug("loading RSA cert successful");
		} catch (IOException e) {
			UnionpayUtils.getLogger().error("loading RSA cert error", e);
		}
	}

	/**
	 * 通过证书路径初始化为公钥证书
	 * @param path
	 * @return
	 */
	private static X509Certificate initCert(String path) {
		X509Certificate encryptCertTemp = null;
		CertificateFactory cf = null;
		FileInputStream in = null;
		try {
			cf = CertificateFactory.getInstance("X.509", "BC");
			in = new FileInputStream(path);
			encryptCertTemp = (X509Certificate) cf.generateCertificate(in);
			// 打印证书加载信息,供测试阶段调试
			UnionpayUtils.getLogger().debug("[" + path + "][CertId="
					+ encryptCertTemp.getSerialNumber().toString() + "]");
		} catch (CertificateException e) {
			UnionpayUtils.getLogger().error("init cert error", e);
		} catch (FileNotFoundException e) {
			UnionpayUtils.getLogger().error("init cert error:file not found", e);
		} catch (NoSuchProviderException e) {
			UnionpayUtils.getLogger().error("load verify cert error:no BC Provider", e);
		} finally {
			if (null != in) {
				try {
					in.close();
				} catch (IOException e) {
					UnionpayUtils.getLogger().error(e.toString());
				}
			}
		}
		return encryptCertTemp;
	}

	/**
	 * 通过keyStore 获取私钥签名证书PrivateKey对象
	 * 
	 * @return
	 */
	public static PrivateKey getSignCertPrivateKey(String signCertPwd) {
		try {
			Enumeration<String> aliasenum = keyStore.aliases();
			String keyAlias = null;
			if (aliasenum.hasMoreElements()) {
				keyAlias = aliasenum.nextElement();
			}
			PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias, signCertPwd.toCharArray());
			return privateKey;
		} catch (KeyStoreException e) {
			UnionpayUtils.getLogger().error("get sign cert private key error", e);
		} catch (UnrecoverableKeyException e) {
			UnionpayUtils.getLogger().error("get sign cert private key error", e);
		} catch (NoSuchAlgorithmException e) {
			UnionpayUtils.getLogger().error("get sign cert private key error", e);
		}
		return null;
	}
	/**
	 * 通过指定路径的私钥证书  获取PrivateKey对象
	 * @return
	 */
	public static PrivateKey getSignCertPrivateKeyByStoreMap(String certPath, String certPwd) {
		if (!keyStoreMap.containsKey(certPath)) {
			loadSignCert(certPath, certPwd);
		}
		try {
			Enumeration<String> aliasenum = keyStoreMap.get(certPath).aliases();
			String keyAlias = null;
			if (aliasenum.hasMoreElements()) {
				keyAlias = aliasenum.nextElement();
			}
			PrivateKey privateKey = (PrivateKey) keyStoreMap.get(certPath)
					.getKey(keyAlias, certPwd.toCharArray());
			return privateKey;
		} catch (KeyStoreException e) {
			UnionpayUtils.getLogger().error("get sign cert private key by store map error", e);
		} catch (UnrecoverableKeyException e) {
			UnionpayUtils.getLogger().error("get sign cert private key by store map error", e);
		} catch (NoSuchAlgorithmException e) {
			UnionpayUtils.getLogger().error("get sign cert private key by store map error", e);
		}
		return null;
	}

	/**
	 * 获取敏感信息加密证书PublicKey
	 * @param encryptCertFile
	 * @return
	 */
	public static PublicKey getEncryptCertPublicKey(String encryptCertFile) {
		if (null == encryptCert) {
			if (!StringUtils.isEmpty(encryptCertFile)) {
				encryptCert = initCert(encryptCertFile);
				return encryptCert.getPublicKey();
			} else {
				UnionpayUtils.getLogger().error("encryptCertFile is empty");
				return null;
			}
		} else {
			return encryptCert.getPublicKey();
		}
	}

	/**
	 * 重置敏感信息加密证书公钥
	 */
	public static void resetEncryptCertPublicKey() {
		encryptCert = null;
	}

	/**
	 * 获取磁道加密证书PublicKey
	 * @param encryptTrackKeyModulus
	 * @param encryptTrackKeyExponent
	 * @return
	 */
	public static PublicKey getEncryptTrackPublicKey(String encryptTrackKeyModulus, String encryptTrackKeyExponent) {
		if (null == encryptTrackKey) {
			initTrackKey(encryptTrackKeyModulus, encryptTrackKeyExponent);
		}
		return encryptTrackKey;
	}

	/**
	 * 通过certId获取验签证书Map中对应证书PublicKey
	 * @param certId 证书物理序号
	 * @param signMethod
	 * @param validateCertDir
	 * @return 通过证书编号获取到的公钥
	 */
	public static PublicKey getValidatePublicKey(String certId, String signMethod, String validateCertDir) {
		X509Certificate cf = null;
		if (certMap.containsKey(certId)) {
			// 存在certId对应的证书对象
			cf = certMap.get(certId);
			return cf.getPublicKey();
		} else {
			// 不存在则重新Load证书文件目录
			initValidateCertFromDir(signMethod, validateCertDir);
			if (certMap.containsKey(certId)) {
				// 存在certId对应的证书对象
				cf = certMap.get(certId);
				return cf.getPublicKey();
			} else {
				UnionpayUtils.getLogger().error("miss certId[" + certId + "] of cert");
				return null;
			}
		}
	}

	/**
	 * 获取配置文件acp_sdk.properties中配置的签名私钥证书certId
	 * 
	 * @return 证书的物理编号
	 */
	public static String getSignCertId() {
		try {
			Enumeration<String> aliasenum = keyStore.aliases();
			String keyAlias = null;
			if (aliasenum.hasMoreElements()) {
				keyAlias = aliasenum.nextElement();
			}
			X509Certificate cert = (X509Certificate) keyStore.getCertificate(keyAlias);
			return cert.getSerialNumber().toString();
		} catch (Exception e) {
			UnionpayUtils.getLogger().error("get sign certId error", e);
		}
		return null;
	}

	/**
	 * 获取敏感信息加密证书的certId
	 * @param encryptCertFile
	 * @return
	 */
	public static String getEncryptCertId(String encryptCertFile) {
		if (encryptCert == null) {
			if (!StringUtils.isEmpty(encryptCertFile)) {
				encryptCert = initCert(encryptCertFile);
				return encryptCert.getSerialNumber().toString();
			} else {
				UnionpayUtils.getLogger().error("encryptCertFile is empty");
				return null;
			}
		} else {
			return encryptCert.getSerialNumber().toString();
		}
	}

	/**
	 * 将签名私钥证书文件读取为证书存储对象
	 * @param pfxkeyfile 证书文件名
	 * @param keypwd 证书密码
	 * @param type 证书类型
	 * @return 证书对象
	 * @throws IOException 
	 */
	private static KeyStore getKeyInfo(String pfxkeyfile, String keypwd, String type) throws IOException {
		UnionpayUtils.getLogger().debug(pfxkeyfile + " sign cert is loading...");
		FileInputStream fis = null;
		try {
			KeyStore ks = KeyStore.getInstance(type, "BC");
			UnionpayUtils.getLogger().debug("loading RSA certfile:[" + pfxkeyfile + "],pwd:[" + keypwd + "],type:[" + type + "]");
			fis = new FileInputStream(pfxkeyfile);
			char[] nPassword = null;
			nPassword = StringUtils.isEmpty(keypwd) ? null: keypwd.toCharArray();
			if (null != ks) {
				ks.load(fis, nPassword);
			}
			return ks;
		} catch (Exception e) {
			UnionpayUtils.getLogger().error("get keyInfo error", e);
			return null;
		} finally {
			if(null!=fis) {
				fis.close();
			}
		}
	}

	/**
	 * 通过签名私钥证书路径，密码获取私钥证书certId
	 * @param certPath
	 * @param certPwd
	 * @return
	 */
	public static String getCertIdByKeyStoreMap(String certPath, String certPwd) {
		if (!keyStoreMap.containsKey(certPath)) {
			// 缓存中未查询到,则加载RSA证书
			loadSignCert(certPath, certPwd);
		}
		return getCertIdIdByStore(keyStoreMap.get(certPath));
	}

	/**
	 * 通过keystore获取私钥证书的certId值
	 * @param keyStore
	 * @return
	 */
	private static String getCertIdIdByStore(KeyStore keyStore) {
		Enumeration<String> aliasenum = null;
		try {
			aliasenum = keyStore.aliases();
			String keyAlias = null;
			if (aliasenum.hasMoreElements()) {
				keyAlias = aliasenum.nextElement();
			}
			X509Certificate cert = (X509Certificate) keyStore
					.getCertificate(keyAlias);
			return cert.getSerialNumber().toString();
		} catch (KeyStoreException e) {
			UnionpayUtils.getLogger().error("get certId by store error", e);
			return null;
		}
	}

	/**
	 * 使用模和指数生成RSA公钥 注意：此代码用了默认补位方式，为RSA/None/PKCS1Padding，不同JDK默认的补位方式可能不同
	 * @param modulus 模
	 * @param exponent 指数
	 * @return
	 */
	private static PublicKey getPublicKey(String modulus, String exponent) {
		try {
			BigInteger b1 = new BigInteger(modulus);
			BigInteger b2 = new BigInteger(exponent);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
			RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
			return keyFactory.generatePublic(keySpec);
		} catch (Exception e) {
			UnionpayUtils.getLogger().error("RSA public key construction failed", e);
			return null;
		}
	}

	/**
	 * 将字符串转换为X509Certificate对象
	 * @param x509CertString
	 * @return
	 */
	public static X509Certificate genCertificateByStr(String x509CertString) {
		X509Certificate x509Cert = null;
		try {
			CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); 
			InputStream tIn = new ByteArrayInputStream(
					x509CertString.getBytes("ISO-8859-1"));
			x509Cert = (X509Certificate) cf.generateCertificate(tIn);
		} catch (Exception e) {
			UnionpayUtils.getLogger().error("gen certificate error", e);			
		}
		return x509Cert;
	}

	/**
	 * 获取验签公钥使用的中级证书
	 * @param middleCertFile
	 * @return
	 */
	public static X509Certificate getMiddleCert(String middleCertFile) {
		if (null == middleCert) {
			if (!StringUtils.isEmpty(middleCertFile)) {
				initMiddleCert(middleCertFile);
			} else {
				UnionpayUtils.getLogger().error("middleCertFile is empty");
				return null;
			}
		}
		return middleCert;
	}

	/**
	 * 获取验签公钥使用的根证书
	 * @param rootCertFile
	 * @return
	 */
	public static X509Certificate getRootCert(String rootCertFile) {
		if (null == rootCert) {
			if (!StringUtils.isEmpty(rootCertFile)) {
				initRootCert(rootCertFile);
			} else {
				UnionpayUtils.getLogger().error("rootCertFile is empty");
				return null;
			}
		}
		return rootCert;
	}

	/**
	 * 获取证书的CN
	 * @param aCert
	 * @return
	 */
	private static String getIdentitiesFromCertficate(X509Certificate aCert) {
		String tDN = aCert.getSubjectDN().toString(); 
		String tPart = "";
		if ((tDN != null)) {
			String tSplitStr[] = tDN.substring(tDN.indexOf("CN=")).split("@");
			if (tSplitStr != null && tSplitStr.length > 2 && tSplitStr[2] != null) {
				tPart = tSplitStr[2];
			}
		}
		return tPart;
	}

	/**
	 * 验证书链
	 * @param cert
	 * @param rootCertFile
	 * @param middleCertFile
	 * @return
	 */
	private static boolean verifyCertificateChain(X509Certificate cert, String rootCertFile ,String middleCertFile){		
		if (cert == null) {
			UnionpayUtils.getLogger().error("cert must not null");
			return false;
		}		
		X509Certificate middleCert = UnionpayCertHolder.getMiddleCert(middleCertFile);
		if (null == middleCert) {
			UnionpayUtils.getLogger().error("middleCert must not null");
			return false;
		}		
		X509Certificate rootCert = UnionpayCertHolder.getRootCert(rootCertFile);
		if (null == rootCert) {
			UnionpayUtils.getLogger().error("rootCert or cert must not null");
			return false;
		}		
		try {		
			X509CertSelector selector = new X509CertSelector();
			selector.setCertificate(cert);	        
			Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();
			trustAnchors.add(new TrustAnchor(rootCert, null));
			PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(trustAnchors, selector);	
			Set<X509Certificate> intermediateCerts = new HashSet<X509Certificate>();
			intermediateCerts.add(rootCert);
			intermediateCerts.add(middleCert);
			intermediateCerts.add(cert);	        
			pkixParams.setRevocationEnabled(false);	
			CertStore intermediateCertStore = CertStore.getInstance("Collection",
					new CollectionCertStoreParameters(intermediateCerts), "BC");
			pkixParams.addCertStore(intermediateCertStore);	
			CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");	        
			@SuppressWarnings("unused")
			PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder.build(pkixParams);
			UnionpayUtils.getLogger().debug("verify cert chain succeed");
			return true;
		} catch (CertPathBuilderException e){
			UnionpayUtils.getLogger().error("verify cert chain fail", e);
		} catch (Exception e) {
			UnionpayUtils.getLogger().error("verify cert chain error: ", e);
		}
		return false;
	}

	/**
	 * 检查证书链
	 * @param cert
	 * @param rootCertFile
	 * @param middleCertFile
	 * @param isCheckCNName
	 * @return
	 */
	public static boolean verifyCertificate(X509Certificate cert, String rootCertFile, String middleCertFile, boolean isCheckCNName) {

		if ( null == cert) {
			UnionpayUtils.getLogger().error("cert must not null");
			return false;
		}
		try {
			cert.checkValidity();//验证有效期
			// cert.verify(middleCert.getPublicKey());
			if(!verifyCertificateChain(cert, rootCertFile, middleCertFile)){
				return false;
			}
		} catch (Exception e) {
			UnionpayUtils.getLogger().error("verifyCertificate fail", e);
			return false;
		}		
		if (isCheckCNName) {
			// 验证公钥是否属于银联
			if(!UnionpayConstants.UNIONPAY_CNNAME.equals(UnionpayCertHolder.getIdentitiesFromCertficate(cert))) {
				UnionpayUtils.getLogger().error("cer owner is not CUP:" + UnionpayCertHolder.getIdentitiesFromCertficate(cert));
				return false;
			}
		} else {
			// 验证公钥是否属于银联
			if (!UnionpayConstants.UNIONPAY_CNNAME.equals(UnionpayCertHolder.getIdentitiesFromCertficate(cert)) 
					&& !"00040000:SIGN".equals(UnionpayCertHolder.getIdentitiesFromCertficate(cert))) {
				UnionpayUtils.getLogger().error("cer owner is not CUP:" + UnionpayCertHolder.getIdentitiesFromCertficate(cert));
				return false;
			}
		}
		return true;		
	}

	/**
	 * 打印系统环境信息
	 */
	private static void printSysInfo() {
		UnionpayUtils.getLogger().debug("================= SYS INFO begin ====================");
		UnionpayUtils.getLogger().debug("os_name:" + System.getProperty("os.name"));
		UnionpayUtils.getLogger().debug("os_arch:" + System.getProperty("os.arch"));
		UnionpayUtils.getLogger().debug("os_version:" + System.getProperty("os.version"));
		UnionpayUtils.getLogger().debug("java_vm_specification_version:"
				+ System.getProperty("java.vm.specification.version"));
		UnionpayUtils.getLogger().debug("java_vm_specification_vendor:"
				+ System.getProperty("java.vm.specification.vendor"));
		UnionpayUtils.getLogger().debug("java_vm_specification_name:"
				+ System.getProperty("java.vm.specification.name"));
		UnionpayUtils.getLogger().debug("java_vm_version:"
				+ System.getProperty("java.vm.version"));
		UnionpayUtils.getLogger().debug("java_vm_name:" + System.getProperty("java.vm.name"));
		UnionpayUtils.getLogger().debug("java.version:" + System.getProperty("java.version"));
		UnionpayUtils.getLogger().debug("java.vm.vendor=[" + System.getProperty("java.vm.vendor") + "]");
		UnionpayUtils.getLogger().debug("java.version=[" + System.getProperty("java.version") + "]");
		printProviders();
		UnionpayUtils.getLogger().debug("================= SYS INFO end =====================");
	}

	/**
	 * 打jre中印算法提供者列表
	 */
	private static void printProviders() {
		UnionpayUtils.getLogger().debug("Providers List:");
		Provider[] providers = Security.getProviders();
		for (int i = 0; i < providers.length; i++) {
			UnionpayUtils.getLogger().debug(i + 1 + "." + providers[i].getName());
		}
	}

	/**
	 * 证书文件过滤器
	 * 
	 */
	static class CerFilter implements FilenameFilter {
		public boolean isCer(String name) {
			if (name.toLowerCase().endsWith(".cer")) {
				return true;
			} else {
				return false;
			}
		}
		public boolean accept(File dir, String name) {
			return isCer(name);
		}
	}

}
